package ckw.gui;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.smartcardio.CardException;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ckw.database.model.AdministratorToken;
import ckw.database.model.Election;
import ckw.database.model.ElectionNode;
import ckw.database.model.Member;
import ckw.election.ElectionService;
import ckw.manager.ManagerController;
import ckw.utils.BeanProvider;
import core.smartCardReader.SmartCardReaderService;
import core.smartCardReader.TokenCard;

@SuppressWarnings("restriction")
public class TokenManagerWindow extends Dialog {
	private static final Logger LOGGER = LoggerFactory.getLogger(TokenManagerWindow.class);

	private Election election;
	protected Shell shell;

	private SmartCardReaderService smartCardReaderService = BeanProvider.smartCardReaderService();
	private ManagerController manager = BeanProvider.managerController();
	private ElectionService electionService = BeanProvider.electionService();

	private ComboViewer cmbVwrMembers;
	private Combo cmbMembers;

	/**
	 * Create the dialog.
	 * 
	 * @param parent
	 * @param style
	 */
	public TokenManagerWindow(Shell parent, Election election) {
		super(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
		setText("Token manager - " + election.getName());

		this.election = election;

		shell = new Shell(getParent(), getStyle());
		shell.setSize(450, 75);
		shell.setText(getText());
		shell.setLayout(new GridLayout(2, false));
	}

	/**
	 * Open the dialog.
	 */
	public void open() {
		createContents();
		shell.open();
		shell.layout();
		Display display = getParent().getDisplay();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the dialog.
	 */
	private void createContents() {
		cmbVwrMembers = new ComboViewer(shell, SWT.READ_ONLY);
		cmbMembers = cmbVwrMembers.getCombo();
		cmbMembers.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				if (getSelectedAdministratorToken() == null) {

				}
			}
		});
		cmbMembers.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		cmbVwrMembers.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				Member member = ((AdministratorToken) element).getMember();
				return member.getSurname() + ", " + member.getName();
			}
		});
		setMembersInput();

		Button btnCreateToken = new Button(shell, SWT.NONE);
		btnCreateToken.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				try {
					List<TokenCard> tokenCardList = smartCardReaderService.getInsertedTokenCards();
					if (tokenCardList.isEmpty() && MainWindow.isInDebugMode() == false) {
						MessageDialog.openInformation(shell, "Info", "No Cards detected.");
					} else {
						if (tokenCardList.size() > 1) {
							if (!MessageDialog.openConfirm(shell, "Confirm", "Detected more than one Card. Token will be written to the first inserted Card. Proceed?")) {
								return;
							}
						}
						AdministratorToken administratorToken = getSelectedAdministratorToken();

						UUID uuid = electionService.generateToken(administratorToken);
						if (MainWindow.isInDebugMode() == false) {
							TokenCard selectedTokenCard = tokenCardList.get(0);
							selectedTokenCard.clearTokens();
							selectedTokenCard.writeAdminToken(uuid);
						}
						MessageDialog.openInformation(shell, "Info", "Administration Token has been succesfully added to the Card.");
					}
				} catch (CardException exception) {
					LOGGER.error(exception.toString());
				}
			}
		});
		GridData gdBtnDone = new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1);
		gdBtnDone.widthHint = 120;
		btnCreateToken.setLayoutData(gdBtnDone);
		btnCreateToken.setText("Create Token");
	}

	private void setMembersInput() {
		cmbVwrMembers.setContentProvider(new ArrayContentProvider());
		List<AdministratorToken> administratorTokenList = getAdministratorTokenList(election);
		AdministratorToken[] administratorTokenArray = administratorTokenList.toArray(new AdministratorToken[administratorTokenList.size()]);
		cmbVwrMembers.setInput(administratorTokenArray);
	}

	private List<AdministratorToken> getAdministratorTokenList(Election election) {
		List<AdministratorToken> administratorTokenList = new ArrayList<AdministratorToken>();

		for (ElectionNode electionNode : election.getNodes()) {
			for (AdministratorToken administratorToken : electionNode.getAdministratorTokens()) {
				administratorTokenList.add(administratorToken);
			}
		}

		return administratorTokenList;
	}

	private AdministratorToken getSelectedAdministratorToken() {
		IStructuredSelection structuredSelection = (IStructuredSelection) cmbVwrMembers.getSelection();
		return (AdministratorToken) structuredSelection.getFirstElement();
	}
}
